package com.teamide.util;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

public class TreeUtil {

	public static JSONArray toTree(JSONArray array, String idName, String parentidName, String childrenName) {
		return new TreeUtil.ToTree(array, idName, parentidName, childrenName).to();
	}

	public static class ToTree {
		private final JSONArray tree;
		private final JSONArray array;
		private final String idName;
		private final String parentidName;
		private final String childrenName;
		private final Set<String> cacheIds = new HashSet<String>();
		private final Map<String, JSONObject> map = new HashMap<String, JSONObject>();

		public ToTree(JSONArray array, String idName, String parentidName, String childrenName) {
			this.tree = new JSONArray();
			this.array = array;
			if (StringUtil.isEmpty(idName)) {
				idName = "id";
			}
			if (StringUtil.isEmpty(parentidName)) {
				parentidName = "parentid";
			}
			if (StringUtil.isEmpty(childrenName)) {
				childrenName = "children";
			}
			this.idName = idName;
			this.parentidName = parentidName;
			this.childrenName = childrenName;

		}

		public JSONArray to() {
			if (array == null) {
				return tree;
			}
			for (int i = 0; i < array.size(); i++) {
				JSONObject one = array.getJSONObject(i);
				String id = one.getString(idName);
				map.put(id, one);
			}

			JSONArray tops = getTops();
			for (int i = 0; i < tops.size(); i++) {
				JSONObject one = tops.getJSONObject(i);
				tree.add(one);
				String id = one.getString(idName);
				cacheIds.add(id);
				JSONArray childrenList = new JSONArray();
				appendChildren(childrenList, id);
				if (childrenList.size() > 0) {
					one.put(childrenName, childrenList);
				}
			}

			return this.tree;
		}

		public JSONArray getTops() {
			JSONArray tops = new JSONArray();
			if (array == null) {
				return tops;
			}
			for (int i = 0; i < array.size(); i++) {
				JSONObject one = array.getJSONObject(i);
				String parentId = one.getString(parentidName);
				boolean findParent = false;
				if (StringUtil.isNotEmpty(parentId)) {
					if (map.get(parentId) != null && map.get(parentId) != one) {
						findParent = true;
					}
				}
				if (!findParent) {
					tops.add(one);
				}
			}
			return tops;
		}

		private void appendChildren(JSONArray childrenList, String id) {
			if (array == null) {
				return;
			}
			for (int i = 0; i < array.size(); i++) {
				JSONObject one = array.getJSONObject(i);
				String parentId = one.getString(parentidName);
				if (StringUtil.isNotEmpty(parentId) && parentId.equals(id)) {

					String id_ = one.getString(idName);
					if (cacheIds.contains(id_)) {
						continue;
					}
					cacheIds.add(id_);

					childrenList.add(one);
					JSONArray childrenList_ = new JSONArray();
					appendChildren(childrenList_, id_);
					if (childrenList_.size() > 0) {
						one.put(childrenName, childrenList_);
					}

				}

			}

		}
	}

}
